package cn.com.common.job.task;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.quartz.DisallowConcurrentExecution;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;

import cn.com.common.constants.Constants;
import cn.com.gas.entity.GasCaminfoForecastEntity;
import cn.com.gas.entity.GasOfflineCamEntity;
import cn.com.gas.entity.GasServerAreaEntity;
import cn.com.gas.entity.GasServerChannelEntity;
import cn.com.gas.entity.GasStationinfoEntity;
import cn.com.gas.entity.GasStationinfoForecastEntity;
import cn.com.gas.entity.GasStaytimeResultEntity;
import cn.com.gas.service.GasCaminfoForecastService;
import cn.com.gas.service.GasOfflineCamService;
import cn.com.gas.service.GasServerAreaService;
import cn.com.gas.service.GasServerChannelService;
import cn.com.gas.service.GasStationinfoForecastService;
import cn.com.gas.service.GasStationinfoService;
import cn.com.gas.service.GasStaytimeResultService;
import cn.com.system.entity.SysParameterEntity;
import cn.com.system.service.SysParameterService;
import cn.com.thirdparty.entity.ProvinceGasStationinfoForecastEntity;
import cn.com.thirdparty.mapper.ProvinceGasStationinfoForecastMapper;
import cn.com.util.TsBqUtils;

@Component("gasStationAndCamForecastProcessTask")
@DisallowConcurrentExecution
public class GasStationAndCamForecastProcessTask {

	@Value("${gasstation.timedTask.gasStationAndCamForecastProcessTask}")
	private String gasStationAndCamForecastProcessTask;

	private Logger logger = LoggerFactory.getLogger(getClass());
	@Autowired
	private SysParameterService sysParameterService;
	@Autowired
	private GasStationinfoService stationinfoService;
	@Autowired
	private GasStaytimeResultService staytimeResultService;
	@Autowired
	private GasStationinfoForecastService stationinfoForecastService;
	@Autowired
	private GasCaminfoForecastService caminfoForecastService;
	@Autowired
	private GasServerAreaService serverAreaService;
	@Autowired
	private GasServerChannelService serverChannelService;
	@Autowired
	private GasOfflineCamService offlineCamService;
	
	@Autowired
	private ProvinceGasStationinfoForecastMapper provinceGasStationinfoForecastMapper;
	
	public void run(String params) throws Exception {
		
		logger.debug("gasStationAndCamForecastProcessTask定时任务正在执行，参数为：{}", params);
		logger.debug("application参数为gasStationAndCamForecastProcessTask：{}", gasStationAndCamForecastProcessTask);

		if (gasStationAndCamForecastProcessTask.equals(Constants.JOB_STOP)) {
			logger.debug("application配置文件控制不执行gasStationAndCamForecastProcessTask定时任务");
			throw new Exception("application配置文件控制不执行gasStationAndCamForecastProcessTask定时任务");
		}

		DateTimeFormatter _formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
		LocalDate yesterday = LocalDate.now().minusDays(1);
		LocalDateTime startOfYesterday = LocalDateTime.of(yesterday, LocalTime.MIN);
		LocalDateTime endOfYesterday = LocalDateTime.of(yesterday, LocalTime.MAX);

		String time = startOfYesterday.format(_formatter);

		if (TsBqUtils.isNotNull(params)) {
			
			String[] _paramsArr = params.split("_");
			
			for (String _params : _paramsArr) {
				
				DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyyMMdd");
				LocalDate localDate = LocalDate.parse(_params, formatter1);
				startOfYesterday = LocalDateTime.of(localDate, LocalTime.MIN);
				endOfYesterday = LocalDateTime.of(localDate, LocalTime.MAX);
				time = localDate.format(_formatter);
				
				logger.debug("gasStationAndCamForecastProcessTask定时任务正在执行，加工日期：{}", _params);
				handleData(startOfYesterday, endOfYesterday, time, _formatter);
				logger.debug("gasStationAndCamForecastProcessTask定时任务正在执行，加工完成：{}", _params);

			}

		} else {
			logger.debug("gasStationAndCamForecastProcessTask定时任务正在执行，加工日期：{}", time);
			handleData(startOfYesterday, endOfYesterday, time, _formatter);
			logger.debug("gasStationAndCamForecastProcessTask定时任务正在执行，加工完成：{}", time);

		}

	}

	// 处理数据
	private String handleData(LocalDateTime startOfYesterday, LocalDateTime endOfYesterday, String time,
			DateTimeFormatter _formatter) throws ParseException {
		
		String pushFlag = "N";
		SysParameterEntity sysParameterEntity = sysParameterService.getById("parameter106");
		if(TsBqUtils.isNotNull(sysParameterEntity)){
			pushFlag = sysParameterEntity.getParameter();
		}
		logger.debug("gasStationAndCamForecastProcessTask给省平台推送标志，标志为：{}", pushFlag);

		
		Date date = new Date();
		
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

		String startDateStr = startOfYesterday.format(formatter);
		String endDateStr = endOfYesterday.format(formatter);
		
		Date[] startOfYesterdayArr = { format.parse(startDateStr) };
		Date[] endOfYesterdayArr = { format.parse(endDateStr) };
		
		// 计算离线率
		LambdaQueryWrapper<GasOfflineCamEntity> queryOfflineCam = Wrappers.lambdaQuery();
		queryOfflineCam.ge(GasOfflineCamEntity::getOfflineTime, localDateTimeToDate(startOfYesterday));
		queryOfflineCam.le(GasOfflineCamEntity::getOfflineTime, localDateTimeToDate(endOfYesterday));
		List<GasOfflineCamEntity> offlineCamList = offlineCamService.list(queryOfflineCam);
		List<GasOfflineCamEntity> TimePeriodList = new ArrayList<GasOfflineCamEntity>();

		for (GasOfflineCamEntity offlineCam : offlineCamList) {

			String offlineTime = offlineCam.getOfflineTime();
			String recoverTime = offlineCam.getRecoverTime();
			try {
				Date offlineTimeDate = format.parse(offlineTime);

				if (TsBqUtils.isNull(recoverTime)) {
					recoverTime = startOfYesterday.format(_formatter) + " 23:59:59";
				} else {
					Date recoverTimeDate = format.parse(recoverTime);
					if (endOfYesterday.isBefore(dateToLocalDateTime(recoverTimeDate))) {
						recoverTime = startOfYesterday.format(_formatter) + " 23:59:59";
					}
				}

				if (dateToLocalDateTime(offlineTimeDate).isBefore(startOfYesterday)) {
					offlineTime = startOfYesterday.format(_formatter) + " 00:00:01";
				}

				Duration duration = Duration.between(dateToLocalDateTime(format.parse(offlineTime)),
						dateToLocalDateTime(format.parse(recoverTime)));

				long minutes = duration.toMillis() / 1000; // 相差秒数

				offlineCam.setTimePeriod(String.valueOf(minutes));
				TimePeriodList.add(offlineCam);

			} catch (ParseException e) {
				logger.error(e.getMessage() + "====offlineCam====" + offlineCam.getId());
				e.printStackTrace();
			}

		}

		List<GasOfflineCamEntity> offlineCamGroup = new ArrayList<GasOfflineCamEntity>();
		if (TsBqUtils.isNotNull(TimePeriodList)) {

			Map<String, List<GasOfflineCamEntity>> groupedItems = TimePeriodList.stream()
					.collect(Collectors.groupingBy(item -> item.getCamId()));
			groupedItems.forEach((category, itemsInCategory) -> {
				if (TsBqUtils.isNotNull(category)) {
					BigDecimal[] timePeriod = { new BigDecimal(0) };
					itemsInCategory.forEach(item -> {
						timePeriod[0] = timePeriod[0].add(new BigDecimal(item.getTimePeriod()));
					});

					GasOfflineCamEntity offlineCam = new GasOfflineCamEntity();
					offlineCam.setCamId(category);

					offlineCam.setTimePeriod(timePeriod[0].toString());

					offlineCamGroup.add(offlineCam);

				}
			});

		}

		// 计算时间情况
		LambdaQueryWrapper<GasStaytimeResultEntity> queryStaytimeResult = Wrappers.lambdaQuery();
        Date startOfYesterdayDate = Date.from(startOfYesterday.atZone(ZoneId.systemDefault()).toInstant());
        Date endOfYesterdayDate = Date.from(endOfYesterday.atZone(ZoneId.systemDefault()).toInstant());

		queryStaytimeResult.ge(GasStaytimeResultEntity::getMessageDisappear, startOfYesterdayDate);
		queryStaytimeResult.le(GasStaytimeResultEntity::getMessageDisappear, endOfYesterdayDate);
		List<GasStaytimeResultEntity> staytimeResultList = staytimeResultService.list(queryStaytimeResult);

		List<GasStaytimeResultEntity> camidAndPriceList = new ArrayList<>();
		// 处理摄像头ID
		for (GasStaytimeResultEntity staytimeResult : staytimeResultList) {

			String camid = staytimeResult.getField5();
			String price = staytimeResult.getPrice();

			if (TsBqUtils.isNull(camid)) {
				// 如果camid 为null 特殊方式获取

				String messageChannel = staytimeResult.getMessageChannel();
				String fromTopic = staytimeResult.getFromTopic();
				String messageAreanumber = staytimeResult.getMessageAreanumber();

				LambdaQueryWrapper<GasServerChannelEntity> serverChannelQueryWrapper = Wrappers.lambdaQuery();

				serverChannelQueryWrapper.eq(GasServerChannelEntity::getTopic, fromTopic);

				List<GasServerChannelEntity> gasServerChannelList = serverChannelService
						.list(serverChannelQueryWrapper);

				if (TsBqUtils.isNotNull(gasServerChannelList)) {

					GasServerChannelEntity serverChannel = gasServerChannelList.get(0);
					String gasServerId = serverChannel.getId();

					LambdaQueryWrapper<GasServerAreaEntity> serverAreaQueryWrapper = Wrappers.lambdaQuery();

					serverAreaQueryWrapper.eq(GasServerAreaEntity::getServerChannel, messageChannel);
					serverAreaQueryWrapper.eq(GasServerAreaEntity::getAreaNumber, messageAreanumber);
					serverAreaQueryWrapper.eq(GasServerAreaEntity::getServerId, gasServerId);

					List<GasServerAreaEntity> serverAreaList = serverAreaService.list(serverAreaQueryWrapper);

					if (TsBqUtils.isNotNull(serverAreaList)) {
						GasServerAreaEntity gasServerAreaEntity = serverAreaList.get(0);
						camid = gasServerAreaEntity.getCamid();
					} else {
						logger.error(
								"存在为空的serverAreaList:" + messageChannel + ":" + messageAreanumber + ":" + gasServerId);

					}
				} else {
					logger.error("存在为空的gasServerChannelList:" + fromTopic);

				}
			}

			if (TsBqUtils.isNotNull(camid)) {

				GasStaytimeResultEntity gasStaytimeResultEntity = new GasStaytimeResultEntity();
				gasStaytimeResultEntity.setPrice(price);
				gasStaytimeResultEntity.setField5(camid);

				camidAndPriceList.add(gasStaytimeResultEntity);
			}
		}

		List<GasStaytimeResultEntity> priceCamGroup = new ArrayList<GasStaytimeResultEntity>();

		if (TsBqUtils.isNotNull(camidAndPriceList)) {
			// 按照摄像头分组
			Map<String, List<GasStaytimeResultEntity>> groupedItems = camidAndPriceList.stream()
					.collect(Collectors.groupingBy(item -> item.getField5()));

			groupedItems.forEach((category, itemsInCategory) -> {
				if (TsBqUtils.isNotNull(category)) {
					BigDecimal[] price = { new BigDecimal(0) };
					itemsInCategory.forEach(item -> {
						price[0] = price[0].add(new BigDecimal(item.getPrice()));
					});

					GasStaytimeResultEntity staytimeResult = new GasStaytimeResultEntity();
					staytimeResult.setField5(category);
					staytimeResult.setPrice(price[0].toString());

					priceCamGroup.add(staytimeResult);
				}
			});
		}

		List<GasCaminfoForecastEntity> caminfoForecastList = new ArrayList<>();

		if (TsBqUtils.isNotNull(priceCamGroup)) {

			for (GasStaytimeResultEntity priceCam : priceCamGroup) {
				String price = priceCam.getPrice();
				String field5 = priceCam.getField5();
				String timePeriod = "0";
				for (GasOfflineCamEntity offlineCam : offlineCamGroup) {
					String camId = offlineCam.getCamId();
					if (field5.equals(camId)) {
						timePeriod = offlineCam.getTimePeriod();
					}
				}

				GasCaminfoForecastEntity caminfoForecast = new GasCaminfoForecastEntity();
				GasStationinfoEntity gasStationinfo = stationinfoService.getById(field5);
				if (TsBqUtils.isNotNull(gasStationinfo)) {

					caminfoForecast.setTime(time);
					caminfoForecast.setStationinfoId(gasStationinfo.getPid());
					caminfoForecast.setCamId(gasStationinfo.getId());
					// caminfoForecast.setTaxorgcode();

					caminfoForecast.setGatherValue(price);
					BigDecimal _price = new BigDecimal(price);

					if (TsBqUtils.isNull(timePeriod) || "0".equals(timePeriod)) {
						caminfoForecast.setForecastValue(price);
					} else {
						
						BigDecimal bigDecimal = new BigDecimal("86400");

						BigDecimal divide = _price.multiply(bigDecimal);

						BigDecimal subtract = bigDecimal.subtract(new BigDecimal(timePeriod));

						BigDecimal multiply = divide.divide(subtract, 2, BigDecimal.ROUND_HALF_UP);

						caminfoForecast.setForecastValue(multiply.toString());

					}

					caminfoForecast.setOfflineTime(timePeriod);
					caminfoForecast.setDeleted(Constants.DELETEED_NOT);
					caminfoForecast.setCreateId("job");
					caminfoForecast.setCreateTime(date);
					caminfoForecastList.add(caminfoForecast);

				} else {
					logger.debug("gasStationAndCamForecastProcessTask定时任务正在执行，gasStationinfo未查询到camid:" + field5);
				}

			}
		}

		// 保存到 gas_caminfo_forecast
		if (TsBqUtils.isNotNull(caminfoForecastList)) {

			for (GasCaminfoForecastEntity caminfoForecast : caminfoForecastList) {

				caminfoForecastService.realDelete(caminfoForecast);
				caminfoForecastService.save(caminfoForecast);

			}

			List<GasStationinfoForecastEntity> stationinfoForecastList = new ArrayList<>();

			// 保存到 gas_stationinfo_forecast
			Map<String, List<GasCaminfoForecastEntity>> groupedItems = caminfoForecastList.stream()
					.collect(Collectors.groupingBy(item -> item.getStationinfoId() + "_" + item.getTime()));

			groupedItems.forEach((category, itemsInCategory) -> {
				if (TsBqUtils.isNotNull(category)) {
					String[] arr = category.split("_");

					String stationinfoId = arr[0];
					String _time = arr[1];

					BigDecimal[] forecastValue = { new BigDecimal(0) };
					BigDecimal[] gatherValue = { new BigDecimal(0) };

					itemsInCategory.forEach(item -> {
						forecastValue[0] = forecastValue[0].add(new BigDecimal(item.getForecastValue())); // 预估值
						gatherValue[0] = gatherValue[0].add(new BigDecimal(item.getGatherValue())); // 采集值

					});

					GasStationinfoForecastEntity stationinfoForecast = new GasStationinfoForecastEntity();
					GasStationinfoEntity stationinfo = stationinfoService.getById(stationinfoId);

					stationinfoForecast.setTime(_time);

					stationinfoForecast.setStationinfoId(stationinfoId);
					stationinfoForecast.setTaxorgcode(stationinfo.getTaxorgcode());

					stationinfoForecast.setGatherValue(gatherValue[0].toString());
					String _forecastValue = forecastValue[0].toString();
					stationinfoForecast.setForecastValue(_forecastValue);

					String gasLocation = stationinfo.getGasLocation();
					String gasCoverage = stationinfo.getGasCoverage();

					if (TsBqUtils.isNotNull(gasCoverage) && TsBqUtils.isNotNull(gasLocation) && !"0".equals(gasCoverage)
							&& !"0".equals(gasLocation)) {

						BigDecimal _forecastValue1 = new BigDecimal(_forecastValue);
						BigDecimal divide = _forecastValue1.divide(new BigDecimal(gasCoverage), 2,
								BigDecimal.ROUND_HALF_UP);
						BigDecimal multiply = divide.multiply(new BigDecimal(gasLocation));
						stationinfoForecast.setForecastValue1(multiply.toString());

					} else {
						stationinfoForecast.setForecastValue1(_forecastValue);

					}

					stationinfoForecast.setGasLocation(gasLocation);
					stationinfoForecast.setGasCoverage(gasCoverage);

					stationinfoForecast.setDeleted(Constants.DELETEED_NOT);
					stationinfoForecast.setCreateId("job");
					stationinfoForecast.setCreateTime(date);

					// 计算 汽油数量 、柴油数量、民营数量、三桶油数量
					// 汽油金额、柴油金额、民营金额、三桶油金额

					// 计算时间情况
					LambdaQueryWrapper<GasStaytimeResultEntity> queryStaytimeResultByStationId = Wrappers.lambdaQuery();
					
					queryStaytimeResultByStationId.ge(GasStaytimeResultEntity::getMessageDisappear,
							startOfYesterdayArr[0]);
					queryStaytimeResultByStationId.le(GasStaytimeResultEntity::getMessageDisappear,
							endOfYesterdayArr[0]);
					queryStaytimeResultByStationId.eq(GasStaytimeResultEntity::getStationId, stationinfoId);
					
					List<GasStaytimeResultEntity> resultList = staytimeResultService
							.list(queryStaytimeResultByStationId);

					String stationinfoName = stationinfo.getName();

					int amountGasoline = 0;
					int amountDiesel = 0;
					int amountPrivate = 0;
					int amountPublic = 0;

					int amountGasCarSmall = 0;
					int amountGasCarMoto = 0;
					int amountGasCarFarming = 0;
					int amountGasCarLighttruck = 0;
					int amountGasCarDiesel = 0;
					
					
					BigDecimal saleGasoline = new BigDecimal("0");
					BigDecimal saleDiesel = new BigDecimal("0");
					BigDecimal salePrivate = new BigDecimal("0");
					BigDecimal salePublic = new BigDecimal("0");

					// BigDecimal gasCarSmall = new BigDecimal("0");;
					// BigDecimal gasCarMoto = new BigDecimal("0");;
					// BigDecimal gasCarFarming = new BigDecimal("0");;
					// BigDecimal gasCarLighttruck = new BigDecimal("0");;
					// BigDecimal gasCarDiesel = new BigDecimal("0");;
					
					
					boolean contains = stationinfoName.contains("中国");
					boolean contains1 = stationinfoName.contains("中石油");
					boolean contains2 = stationinfoName.contains("中石化");

					if (TsBqUtils.isNotNull(resultList)) {
						for (GasStaytimeResultEntity entity : resultList) {
							String price = entity.getPrice();
							String oils = entity.getOils();
							String ruleid = entity.getMessageRuleid();
							
							if (contains || contains1 || contains2) {
								// 三桶油
								amountPublic++;
								salePublic = salePublic.add(new BigDecimal(price));

							} else {
								// 地方站
								amountPrivate++;
								salePrivate = salePrivate.add(new BigDecimal(price));
							}

							if (oils.equals("汽油")) {
								// 汽油
								amountGasoline++;
								saleGasoline = saleGasoline.add(new BigDecimal(price));
							} else {
								// 柴油
								amountDiesel++;
								saleDiesel = saleDiesel.add(new BigDecimal(price));
							}
							
							if (ruleid.equals(Constants.GAS_CAR_SMALL)) {
								amountGasCarSmall++;
							} else if (ruleid.equals(Constants.GAS_CAR_MOTO)) {
								// 摩托车
								amountGasCarMoto++;
							} else if (ruleid.equals(Constants.GAS_CAR_FARMING)) {
								// 农用车
								amountGasCarFarming++;
							} else if (ruleid.equals(Constants.GAS_CAR_LIGHTTRUCK)) {
								// 轻卡
								amountGasCarLighttruck++;
							} else {
								// 柴油车
								amountGasCarDiesel++;
							}
						}
					}

					stationinfoForecast.setAmountGasoline(amountGasoline + "");
					stationinfoForecast.setAmountDiesel(amountDiesel + "");
					stationinfoForecast.setAmountPrivate(amountPrivate + "");
					stationinfoForecast.setAmountPublic(amountPublic + "");

					stationinfoForecast.setAmountGasCarSmall(amountGasCarSmall + "");
					stationinfoForecast.setAmountGasCarMoto(amountGasCarMoto + "");
					stationinfoForecast.setAmountGasCarFarming(amountGasCarFarming + "");
					stationinfoForecast.setAmountGasCarLighttruck(amountGasCarLighttruck + "");
					stationinfoForecast.setAmountGasCarDiesel(amountGasCarDiesel + "");
					
					stationinfoForecast.setSaleGasoline(saleGasoline.toString());
					stationinfoForecast.setSaleDiesel(saleDiesel.toString());
					stationinfoForecast.setSalePrivate(salePrivate.toString());
					stationinfoForecast.setSalePublic(salePublic.toString());
					
					stationinfoForecastList.add(stationinfoForecast);

				}
			});

			if (TsBqUtils.isNotNull(stationinfoForecastList)) {

				for (GasStationinfoForecastEntity stationinfoForecast : stationinfoForecastList) {
					// 删除数据
					stationinfoForecastService.realDelete(stationinfoForecast);
					stationinfoForecastService.save(stationinfoForecast);
					
					try {
						
						if(pushFlag.equals("Y")){
							// 类转转换 推送
							ProvinceGasStationinfoForecastEntity entity = new ProvinceGasStationinfoForecastEntity();
							BeanUtils.copyProperties(stationinfoForecast, entity);
							provinceGasStationinfoForecastMapper.realDelete(entity);
							provinceGasStationinfoForecastMapper.insert(entity);
							
						}
						
					} catch (Exception e) {
						logger.error("推送省平台异常：" + e.getMessage());
					}
					
				}
			}

		}
		return null;
	}

	private static LocalDateTime dateToLocalDateTime(Date date) {
		Instant instant = date.toInstant();
		return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());

	}

	private static Date localDateTimeToDate(LocalDateTime localDateTime) {
		ZoneId zoneId = ZoneId.systemDefault();
		ZonedDateTime zdt = localDateTime.atZone(zoneId);
		return Date.from(zdt.toInstant());
	}
	
}
